﻿namespace HZY.Framework.Core.Aop.Attributes;

/// <summary>
/// aop 拦截器
/// </summary>
public class AopMoAttribute : MoAttribute
{
    static readonly AsyncLocal<IServiceProvider> ServiceProvider = new();
    static readonly AsyncLocal<IServiceScope?> Scope = new();

    /// <summary>
    /// 设置服务提供者
    /// </summary>
    /// <param name="serviceProvider"></param>
    public static void SetServiceProvider(IServiceProvider serviceProvider) => ServiceProvider.Value = serviceProvider;

    /// <summary>
    /// 创建域服务
    /// </summary>
    /// <returns></returns>
    protected static IServiceScope? GetScope()
    {
        Scope.Value ??= App.Host?.Services?.CreateScope();
        return Scope.Value;
    }

    /// <summary>
    /// 获取服务
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    protected static object? GetService(Type type)
    {
        if (App.Host == null) return default!;

        try
        {
            if (ServiceProvider.Value != null)
            {
                return ServiceProvider.Value.GetService(type);
            }

            return GetScope()?.ServiceProvider.GetService(type);
        }
        catch (Exception)
        {
            return GetScope()?.ServiceProvider.GetService(type);
        }
    }

    /// <summary>
    /// 获取服务
    /// </summary>
    /// <typeparam name="TService"></typeparam>
    /// <returns></returns>
    protected static TService? GetService<TService>()
    {
        if (App.Host == null) return default!;

        try
        {
            if (ServiceProvider.Value != null)
            {
                return ServiceProvider.Value.GetService<TService>();
            }

            var scope = GetScope();

            return scope is null ? default : scope!.ServiceProvider.GetService<TService>();
        }
        catch (Exception)
        {
            var scope = GetScope();

            return scope is null ? default : scope!.ServiceProvider.GetService<TService>();
        }
    }

    /// <summary>
    /// 方法退出时，不论方法执行成功还是异常，都会执行
    /// </summary>
    /// <param name="context"></param>
    public override void OnExit(MethodContext context)
    {
        Scope.Value?.Dispose();
        Scope.Value = null;
    }

    /// <summary>
    /// 获取日志对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="context"></param>
    /// <returns></returns>
    protected static ILogger? GetLogger<T>(MethodContext context)
    {
        try
        {
            // 获取日志对象
            var type = typeof(ILogger<>).MakeGenericType(context.TargetType!);
            return GetService(type) as ILogger;
        }
        catch (Exception)
        {
            // 获取日志对象
            var type = typeof(ILogger<>).MakeGenericType(typeof(T));
            return GetService(type) as ILogger;
        }
    }
}